﻿#include "LumFontIcon.h"
#include "LumDebug.h"
#include <QFontDatabase>
#include <QFile>

struct LumFontIcon::LumIconFont {
    QString family;
    QString prefix;
    QMap<QString, char32_t> codeMap;
    bool IsValid() const {
        return !family.isEmpty();
    }
};

struct LumFontIcon::LumFontIconData {
    QMap<QString, LumFontIcon::LumIconFont> fontMap;
};

LumFontIcon::~LumFontIcon() { }

LumFontIcon& LumFontIcon::Instance() {
    static LumFontIcon fontIcon;
    return fontIcon;
}

LumFontIcon::LumFontIcon() {
    d.reset(new LumFontIconData);
}

std::optional<QString> LumFontIcon::AddFont(const QString& fontFile, const QString& codeMapFile) {
    std::optional<QString> result;
    const auto &fontId = QFontDatabase::addApplicationFont(fontFile);
    if(fontId == -1) {
        return result;
    }

    QFile mapFile(codeMapFile);
    if(!mapFile.exists()) {
        DEBUG << "Code 映射表文件不存在";
        QFontDatabase::removeApplicationFont(fontId);
    }

    if(!mapFile.open(QFile::ReadOnly | QFile::Text)) {
        DEBUG << "Code 映射表文件打开失败";
        QFontDatabase::removeApplicationFont(fontId);
    }

    const auto &familyList = QFontDatabase::applicationFontFamilies(fontId);
    const auto &family = familyList.first();

    LumIconFont iconFont;
    iconFont.family = family;


    QTextStream stream(&mapFile);

    auto &map = iconFont.codeMap;

    QString line;
    if(stream.readLineInto(&line)) {
        const auto &columns = line.split(",");
        if(columns.count() > 1) {
            //const auto &colum0 = columns.at(0);
            //const auto &colum1 = columns.at(1);
            //DEBUG << QString("colum0: %1, colum1: %2").arg(colum0).arg(colum1);
        }
    }
    while (stream.readLineInto(&line)) {
        const auto &columns = line.split(",");
        if(columns.count() > 1) {
            const QString &codeString = columns.at(0);
            const auto &code = codeString.toUInt(nullptr, 16);
            const auto &name = columns.at(1);
            map.insert(name, code);
            DEBUG << QString("Code: %1, Name: %2").arg(codeString).arg(name);
        }
    }

    mapFile.close();
    result = family;
    d->fontMap.insert(family, iconFont);
    return result;
}

QStringList LumFontIcon::Families() const {
    return d->fontMap.keys();
}

char32_t LumFontIcon::IconCode(const QString& name, const QString& family) const {
    const auto &font = d->fontMap.value(family);
    if(!font.IsValid()) {
        return -1;
    }

    return font.codeMap.value(name);
}

QChar LumFontIcon::IconChar(const QString& name, const QString& family) const {
    const auto &code = IconCode(name, family);
    if(code == -1) {
        return QChar();
    }

    return QChar(code);
}

QStringList LumFontIcon::IconNames(const QString& family) const {
    const auto &font = d->fontMap.value(family);
    if(!font.IsValid()) {
        return QStringList();
    }

    return font.codeMap.keys();
}

QMap<QString, char32_t> LumFontIcon::CodeMap(const QString& family) const {
    const auto &font = d->fontMap.value(family);
    if(!font.IsValid()) {
        return QMap<QString, char32_t>();
    }

    return font.codeMap;
}
